﻿using ILRuntime.Mono.Cecil;
using Smart.Model.UI;
using System;
using System.Collections;
using UnityEngine;

namespace Smart.Model
{
    public class GameApplication : MonoBehaviour
    {
        protected bool initialized = false;
        protected bool started = false;
        [SerializeField]
        protected GameObject UIRoot;

        private void Awake()
        {
            Entry.Instance = new Entry(this.gameObject,UIRoot);
            DontDestroyOnLoad(this.gameObject);
        }

        protected void Start()
        {
            //string path = "E:/NGUIFrame/U3D/Assets/Res/Table/UnionBuff.bytes";
            //var datas = System.IO.File.ReadAllBytes(path);
            //var gItems = GDecoder.LoadTable(datas);

            //TABLE.UNIONBUFF.__data = gItems;

            //GDecoder.BindTableData(gItems, (TableHandle handle) =>
            //{
            //    var item = new UNIONBUFF();
            //    item.handle = handle;
            //    return item;
            //});

            Logger.Log("<color=#00ff00>[游戏启动:Start]...</color>");
            initialized = false;
            StartCoroutine(Startup());
        }

        protected string GetHttpServer()
        {
            return "http://127.0.0.1:8080";
        }

        protected string GetConfigPath()
        {
#if UNITY_EDITOR
            return $"Config/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}";
#else
            return "Config";
#endif
        }

        protected string GetAssetBundlePath()
        {
#if UNITY_EDITOR
            return $"AssetBundles/{UnityEditor.EditorUserBuildSettings.activeBuildTarget}";
#else
            return "AssetBundles";
#endif
        }

        protected IEnumerator LoadConfigs(string url,System.Action onFailed)
        {
            yield return Entry.Instance.ResourceComponent.LoadBytes(url,onFailed);
        }

        protected IEnumerator CheckGameVersion(System.Action onFailed)
        {
            var server = GetHttpServer();
            var url = $"{server}/{GetAssetBundlePath()}/";

            if (!PlayerPrefs.HasKey(ResourceComponent.gameVersionKey))
            {
                bool succeed = true;
                yield return Entry.Instance.ResourceComponent.DownloadVersionAssetBundles(url, ()=> { succeed = false; });
                if(!succeed)
                {
                    onFailed?.Invoke();
                    yield break;
                }

                Logger.Log("<color=#00ff00>[首次登录下载成功]...</color>");
                yield break;
            }

            var base64String = PlayerPrefs.GetString(ResourceComponent.gameVersionKey);
            byte[] bytes = Convert.FromBase64String(base64String);
            int pos = 0;
            var version = bytes.ReadString(ref pos);
            Logger.Log($"<color=#00ff00>[上次登录版本号]:[{version}]</color>");
            Logger.Log($"<color=#00ff00>[服务器版本号]:[{Entry.Instance.ResourceComponent.version}]</color>");
            if (string.Equals(version, Entry.Instance.ResourceComponent.version))
            {
                Logger.Log("<color=#3d4e5f>[不需要进行版本更新]</color>");
                yield break;
            }

            Logger.Log("<color=#00ff00>[需要进行版本更新]</color>");
            yield return Entry.Instance.ResourceComponent.UpgradeVersionAssetBundles(url,()=>
            {
                Logger.LogError($"[版本升级失败]...from [{version}] to [{Entry.Instance.ResourceComponent.version}]");
                onFailed?.Invoke();
            });
        }

        protected IEnumerator Startup()
        {
            Logger.Log("<color=#00ff00>[开始加载配置文件]...</color>");
            var server = GetHttpServer();
            var url = $"{server}/{GetConfigPath()}/abInfo.bytes";
            bool succeed = true;
            yield return LoadConfigs(url,()=> { succeed = false; });
            if (!succeed)
                yield break;
            Logger.Log("<color=#00ff00>[加载配置文件成功]...</color>");

            Logger.Log("<color=#00ff00>[校验游戏版本号]...</color>");
            yield return CheckGameVersion(() => { succeed = false; });
            if(!succeed)
            {
                Logger.LogError("<color=#ff0000>[校验游戏版本号失败]...</color>");
                yield break;
            }

            Logger.Log("<color=#00ff00>[加载热更层代码]...</color>");
            var codeUrl = $"{server}/{GetAssetBundlePath()}";
            yield return HotfixManager.Instance.LoadAssemblies(codeUrl,"code",()=>
            {
                succeed = false;
            });
            if (!succeed)
                yield break;

            Logger.Log("<color=#00ff00>[加载游戏表格数据]...</color>");
            yield return Entry.Instance.ResourceComponent.LoadAssetBundle(codeUrl, "table",null,() =>
            {
                succeed = false;
            });
            if (!succeed)
            {
                Logger.LogError($"[加载游戏表格BUNDLE失败]");
                HotfixManager.Instance.Destroy();
                yield break;
            }

            Logger.Log("<color=#00ff00>[启动热更层注册器]...</color>");
            HotfixManager.Instance.Awake();

            yield return Entry.Instance.TableComponent.LoadTables(Entry.Instance.ResourceComponent,() =>
            {
                succeed = false;
            });
            if (!succeed)
            {
                Logger.LogError($"[加载游戏数据表失败]");
                HotfixManager.Instance.Destroy();
                yield break;
            }

            Entry.Instance.ResourceComponent.UnLoadAssetBundle("table");

            yield return Entry.Instance.ResourceComponent.LoadNeededBundles(()=>
            {
                succeed = false;
            });

            if(!succeed)
            {
                Logger.LogError("<color=#00ff00>[启动热更层失败]:[资源加载失败]...</color>");
                HotfixManager.Instance.Destroy();
                yield break;
            }

            Logger.Log("<color=#00ff00>[启动热更层]...</color>");
            HotfixManager.Instance.Start();

            Logger.Log("<color=#00ff00>[等待热更层任务]...</color>");
            while (!HotfixManager.Instance.Ready)
            {
                yield return null;
            }

            initialized = true;
            Logger.Log("<color=#00ff00>[游戏启动成功]...</color>");
        }

        private void Update()
        {
            if (initialized)
            {
                try
                {
                    Entry.Instance.EventSystem.Update();
                    HotfixManager.Instance.Update();
                    this.started = true;
                }
                catch (System.Exception e)
                {
                    Logger.LogError(e.Message);
                }
            }
        }

        private void LateUpdate()
        {
            if (initialized && started)
            {
                try
                {
                    Entry.Instance.EventSystem.LateUpdate();
                    HotfixManager.Instance.LateUpdate();
                }
                catch (System.Exception e)
                {
                    Logger.LogError(e.Message);
                }
            }
        }

        private void OnDestroy()
        {
            HotfixManager.Instance.Destroy();
            Entry.Instance.Dispose();
            Entry.Instance = null;
            HotfixManager.Instance.ApplicationQuit();
        }
    }
}